package acmtests;

import java.io.File;
import java.util.*;

import edg.acm.ConfigurationException;
import edg.acm.ConfigurationModel;
import edg.acm.ConfigurationParameter;
import edg.acm.ConfigurationWorker;
import edg.acm.IllegalValueException;
import edg.acm.ValidationException;

public class testing 
{
	public static void main(String[] args)
	{
		//setup for command line arguments - i.e. valid-set, invalid-set, etc
		int alength = args.length;
		if(alength != 1)
		{
			System.out.println("Incorrect number of arguments");
		}
		else	
			System.out.println(args[0]);
		
		
		
		
		//first test
		if(args[0].equalsIgnoreCase("valid-set"))
		{
			//-ITP will create a CM.
			//-ITP will set() the specified parameter with each value generated for that parameter.
			//-ITP will keep track of exceptions received when setting a valid value and the value that caused it.
			//-ITP will generate a report detailing what values caused exceptions.
			
			ConfigurationModel cm = ConfigurationModel.createNewConfigModel();
			List parm = ConfigurationParameter.getParameters();
			String curParm;
			String curParmName;
			ConfigurationParameter curParmObj;
			
			int[] array = new int[parm.size()];
			
			int errorCount = 0;
			
			//for every parameter...
			for(int a = 0; a < parm.size(); a++)
			{
				//check the type and the bounds
				curParmObj = (ConfigurationParameter)parm.get(a);
				curParmName = curParmObj.getName();
				System.out.println("Currently Testing Parameter: " + curParmName);
				
				Class parmClass = curParmObj.getType();
				String classType = parmClass.toString();
				
				//if the type is an integer, do the integer test
				if(classType.equals("class java.lang.Integer"))
				{
					//grab the bounds, and use it to create the random number gen
					//since theres no good way to handle nulls, it will the MAX_VALUE, MIN_VALUE
					int min = curParmObj.getMinimum().intValue();
					int max = curParmObj.getMaximum().intValue();
					
					//making sure there are bounds
					if(min != Integer.MIN_VALUE || max != Integer.MAX_VALUE)
					{
						Random gen = new Random(11111);
						int ran;
						
							//generate 1000 numbers that fit within the bounds randomly
							for(int i = 0; i < 1000; i++)
							{
								//does not check for negative bounds -- assuming all mins are positive
								ran = gen.nextInt((max-min)) + min;
								
								//setting...
								if(!cm.setValue(curParmName, ran))
								{
									System.out.println(curParmName + " " + ran +
											" was NOT successful");
									
									errorCount++;
								}
								else
								{
									System.out.println(curParmName + " " + ran + " was set successfully");
								}
							}
							//cornercase time
							if(!cm.setValue(curParmName, min))
							{
								System.out.println(curParmName + " MIN: " + min +
										" was NOT sucessful");
							}
							if(!cm.setValue(curParmName, max))
							{
								System.out.println(curParmName + " MAX: " + max +
										" was NOT sucessful");
							}
							array[a] = errorCount;
							errorCount = 0;	
					}
					//no bounds, then nothing to test
					else 
						System.out.println(curParmName + " has no bounds to check");					
				}
				
			}
			
			System.out.println("For each parameter with bounds are tested 1002 times: \n");
			
			for(int b = 0; b < parm.size(); b++)
			{
				System.out.println(((ConfigurationParameter)parm.get(b)).getName() + " had " + array[b] + " errors");
				
			}
				
		}
		
		//invalid set, pretty much testing numbers bigger than max, and less than min
		if (args[0].equalsIgnoreCase("invalid-set"))
		{
			ConfigurationModel cm = ConfigurationModel.createNewConfigModel();
			List parm = ConfigurationParameter.getParameters();
			String curParm;
			String curParmName;
			ConfigurationParameter curParmObj;
			
			int array[] = new int[parm.size()];
			int arrayE[] = new int[parm.size()];
			int operationCount = 0;
			int errorCount = 0;
			
			for(int a = 0; a < parm.size(); a++)
			{
				
				
				curParmObj = (ConfigurationParameter)parm.get(a);
				curParmName = curParmObj.getName();
				System.out.println("Currently Testing Parameter: " + curParmName);
				
				
				System.out.println("Testing: Negatives");
				//to test, since all are ints, we are going to test chars and negs as well
				for(int i = 0; i < 5; i++)
				{
					Random gen = new Random();
					
					int ran = - gen.nextInt(Integer.MAX_VALUE);
					try{
						operationCount++;
						cm.setValue(curParmName, ran);
					}
					catch(IllegalValueException e)
					{
						errorCount++;
						System.out.println(e.getMessage() + " " + ran);
					}
					
				}
				
				System.out.println("Testing: Invalid Data Type - Strings");
				String testString = "This is an invalid input";
								
				
				try{
					operationCount++;
					cm.setValue(curParmName, testString);
				}
				catch (IllegalValueException e)
				{
					errorCount++;
					System.out.println(e.getMessage() + " " + testString);
				}
								
				System.out.println("Testing: Bounds -MAX ");
				
				int min = curParmObj.getMinimum().intValue();
				int max = curParmObj.getMaximum().intValue();
				
				//any number between max value and the max bound
				if(max != Integer.MAX_VALUE)
				{
					for(int i = 0; i < 10; i++)
					{
						Random gen = new Random();
						
						int ran = gen.nextInt(Integer.MAX_VALUE - max)+ max;
						
						try
						{
							operationCount++;
							cm.setValue(curParmName, ran);
						}
						catch(IllegalValueException e)
						{
							System.out.println(e.getMessage() + " " + ran);
							errorCount++;
						}
						
					}
				}
				System.out.println("Testing: Bounds -MIN ");
				//any number between 0 and min bound
				if(min > 0)
				{
					for(int i = 0; i < 10; i++)
					{
						Random gen = new Random();
						int ran = gen.nextInt(min);
						try
						{
							operationCount++;
							cm.setValue(curParmName, ran);
						}
						catch(IllegalValueException e)
						{
							errorCount++;
							System.out.println(e.getMessage() + " " + ran);
						}
						
					}
				}
				else
				{
					try
					{
						operationCount++;
						cm.setValue(curParmName, 0);
					}
					catch(ConfigurationException e)
					{
						errorCount++;
						System.out.println(e.getMessage() + " 0");
					}
				}
				
				array[a] = operationCount;
				arrayE[a] = errorCount;
				operationCount = 0;
				errorCount = 0;
			}
			
			System.out.println("\nSummary of operations and detected errors");
			for(int b = 0; b < parm.size(); b++)
			{
				System.out.println(((ConfigurationParameter)parm.get(b)).getName() + " had " 
						+ arrayE[b] + " errors out of " + array[b] + " operations" );
			}
			
		}
		if (args[0].equalsIgnoreCase("get-verify"))
		{
			
			ConfigurationModel cm = ConfigurationModel.createNewConfigModel();
			List parm = ConfigurationParameter.getParameters();
			String curParm;
			String curParmName;
			ConfigurationParameter curParmObj;
			
			//random seed generator
			Random seeder = new Random(777);
			
			for(int b = 0; b < 1000; b++)
			{
				int seed = seeder.nextInt(10000);
				//setting the random seed
				Random gen = new Random(seed);
				for(int a = 0; a < parm.size(); a++)
				{
					curParmObj = (ConfigurationParameter)parm.get(a);
					curParmName = curParmObj.getName();
				
					
					
					int min = curParmObj.getMinimum().intValue();
					int max = curParmObj.getMaximum().intValue();
					
					int ran = gen.nextInt((max-min)) + min;
					//setting...
					if(!cm.setValue(curParmName, ran))
					{
						System.out.println(curParmName + " " + ran +
								" was NOT sucessful");
					}
					else
					{
						System.out.println(curParmName + " = " + ran);
					}
					
				}
				//setting with same seed, should return the same values as before
				Random genX = new Random(seed);
                                
                                //goes through each parameter in the same order as before,
                                //getValue() ?= same-seeded random value
				for(int a = 0; a < parm.size(); a++)
				{
					curParmObj = (ConfigurationParameter)parm.get(a);;
					curParmName = curParmObj.getName();
					
					int min = curParmObj.getMinimum().intValue();
					int max = curParmObj.getMaximum().intValue();
					
					
					
					Object val = cm.getValue(curParmName);
					int valu = ((Integer)val).intValue();
					int ran = genX.nextInt((max-min)) + min;
					
					System.out.println("Value the parameter should be: "+ valu + " vs. " + ran);
					if(valu != ran)
					{
						System.out.println("Error in " + curParmName + "run: " + b);
						break;
					}
					
				}
				
			}
		}
		if (args[0].equalsIgnoreCase("required"))
		{
			ConfigurationModel cm = ConfigurationModel.createNewConfigModel();
			List parm = ConfigurationParameter.getParameters();
			
			int five = 5;
			
			System.out.println("Setting Doctor...\n\n\n");
			
			cm.setValue("doctor", five);
			
			for(int a = 0; a < parm.size(); a++)
			{
				if(((ConfigurationParameter)parm.get(a)).isRequired())
				{
					System.out.println(((ConfigurationParameter)parm.get(a)).getName() + " is required");
				}
				else
					System.out.println(((ConfigurationParameter)parm.get(a)).getName() + " is NOT required");
				
			}
				try {
					ConfigurationWorker.runConfiguration(cm);
				} catch (ValidationException e) {
					// TODO Auto-generated catch block
					
					List missing = e.getMissing();
					
					for(int i = 0; i < missing.size(); i++)
						System.out.println("Error! Required variable is NULL: " + missing.get(i));
				}
						
			
		}
		
	}

}
